/**
 * 图片压缩模块
 * 提供图片压缩相关的功能
 */
import { ElMessage } from 'element-plus';

/**
 * 图片压缩方法
 * @param {File} file - 原始文件对象
 * @param {Object} options - 压缩选项
 * @param {Number} options.maxSize - 文件大小限制（MB）
 * @param {Number} options.compressSize - 压缩阈值（MB）
 * @param {Boolean} options.enableCompress - 是否启用压缩
 * @param {Number} options.compressQuality - 压缩质量(0-1)
 * @param {Number} options.maxCompressTries - 最大压缩尝试次数
 * @returns {Promise<File>} - 压缩后的文件对象
 */
export const compressImage = (file, options) => {
  return new Promise((resolve, reject) => {
    const { maxSize, compressSize, enableCompress, compressQuality = 1, maxCompressTries = 5 } = options;
    console.log('开始压缩图片:', file.name, '大小:', (file.size / 1024 / 1024).toFixed(2), 'MB');
    
    // 再次检查文件大小（多重保险）
    if (file.size / 1024 / 1024 >= maxSize) {
      console.error('文件大小超出限制，跳过压缩', (file.size / 1024 / 1024).toFixed(2), 'MB', '>', maxSize, 'MB');
      return reject(new Error(`文件太大，跳过压缩`));
    }
    
    // 如果禁用压缩或文件已经小于目标大小，则直接返回原文件
    if (!enableCompress || file.size / 1024 / 1024 < compressSize) {
      console.log('跳过压缩 - 文件小于阈值或压缩已禁用', 
        '启用压缩:', enableCompress, 
        '文件大小:', (file.size / 1024 / 1024).toFixed(2), 'MB', 
        '压缩阈值:', compressSize, 'MB');
      return resolve(file);
    }

    // 如果文件大小超过maxSize，直接拒绝
    // 这是一个备用安全检查，正常情况下 beforeImageUpload 已拦截超大文件
    if (file.size / 1024 / 1024 >= maxSize) {
      console.error('文件大小超出限制（备用安全检查）', (file.size / 1024 / 1024).toFixed(2), 'MB', '>', maxSize, 'MB');
      // 不再显示错误提示，因为 beforeImageUpload 已经显示了
      return reject(new Error(`图片太大，无法压缩`));
    }

    // 计算动态压缩比率 - 文件越大，压缩力度越大；文件接近阈值，压缩力度越小
    const fileSizeMB = file.size / 1024 / 1024;
    
    // 直接使用0.95作为初始压缩质量，通过尺寸而非质量控制压缩结果
    const initialQuality = 0.95;
    
    // 设置最小允许压缩大小，防止过度压缩
    // 无论图片多大，最多压缩到原始大小的20%，或者compressSize中的较大值
    const minAllowedSizeMB = Math.max(fileSizeMB * 0.2, compressSize * 0.7);
    
    console.log('执行压缩 - 条件设置:',
      '文件大小:', fileSizeMB.toFixed(2), 'MB',
      '压缩阈值:', compressSize.toFixed(2), 'MB',
      '最小允许大小:', minAllowedSizeMB.toFixed(2), 'MB',
      '初始压缩质量:', initialQuality.toFixed(2));

    // 创建一个新的图像对象
    const img = new Image();
    img.src = URL.createObjectURL(file);
    
    // 设置图片加载超时
    const imageLoadTimeout = setTimeout(() => {
      reject(new Error('图片加载超时'));
    }, 30000); // 30秒超时
    
    img.onload = () => {
      clearTimeout(imageLoadTimeout);
      
      // 计算合适的压缩比例，保持原始宽高比
      let width = img.width;
      let height = img.height;
      const megaPixels = (width * height) / 1000000;
      
      // 对于高像素图片，先进行适当的尺寸缩小
      // 使用更智能的尺寸缩放策略
      let MAX_DIMENSION;
      
      if (megaPixels > 20) { // 超过2000万像素的极大图片
        MAX_DIMENSION = 3000;
      } else if (megaPixels > 12) { // 1200-2000万像素的大图片
        MAX_DIMENSION = 3500;
      } else if (megaPixels > 8) { // 800-1200万像素的图片
        MAX_DIMENSION = 4000;
      } else {
        MAX_DIMENSION = 4500; // 其他图片保持较大尺寸
      }
      
      if (width > MAX_DIMENSION || height > MAX_DIMENSION) {
        console.log('图片尺寸过大，进行缩放:', width, 'x', height, '(', megaPixels.toFixed(1), '百万像素)');
        const ratio = Math.min(MAX_DIMENSION / width, MAX_DIMENSION / height);
        width = Math.floor(width * ratio);
        height = Math.floor(height * ratio);
        console.log('缩放后尺寸:', width, 'x', height);
      } else {
        console.log('图片尺寸适中，保持原始尺寸:', width, 'x', height, '(', megaPixels.toFixed(1), '百万像素)');
      }
      
      // 创建canvas用于压缩
      const canvas = document.createElement('canvas');
      const ctx = canvas.getContext('2d');
      
      // 设置canvas尺寸
      canvas.width = width;
      canvas.height = height;
      
      // 绘制图片到canvas
      ctx.clearRect(0, 0, width, height);
      ctx.drawImage(img, 0, 0, width, height);
      
      // 释放图片对象URL
      URL.revokeObjectURL(img.src);
      
      // 直接将目标设置为compressSize，不再使用比例
      // 这样压缩的目标就直接是用户设置的阈值大小
      const targetSize = compressSize;
      
      // 递归压缩，逐步降低质量直到小于目标大小，但不小于最小允许大小
      const compressWithQuality = (quality, tries = 0) => {
        console.log(`压缩尝试 #${tries+1}, 质量: ${quality.toFixed(2)}`);
        
        // 获取压缩后的文件
        canvas.toBlob((blob) => {
          if (!blob) {
            console.error('压缩失败，无法获取Blob对象');
            return reject(new Error('图片压缩失败 - 无法获取Blob'));
          }
          
          const blobSizeMB = blob.size / 1024 / 1024;
          console.log(`压缩结果: ${blobSizeMB.toFixed(2)}MB (目标: <${targetSize}MB, 最小: ${minAllowedSizeMB.toFixed(2)}MB)`);
          
          // 以下情况停止压缩：
          // 1. 大小小于目标大小
          // 2. 大小小于最小允许大小（添加保护，防止过度压缩）
          // 3. 达到最大尝试次数
          // 4. 质量已经很低了（低于0.75）
          if (blobSizeMB < targetSize || blobSizeMB < minAllowedSizeMB || 
              tries >= maxCompressTries || quality <= 0.75) {
              
            // 如果尺寸已经小于目标大小，直接使用当前结果
            if (blobSizeMB < targetSize) {
              console.log(`压缩成功: 文件大小${blobSizeMB.toFixed(2)}MB小于目标大小${targetSize}MB`);
            } 
            // 如果已经小于最小允许大小，使用前一次的结果（如果有）
            else if (blobSizeMB < minAllowedSizeMB && tries > 0) {
              console.warn(`达到最小允许大小保护，停止压缩`);
            }
            // 如果达到最大尝试次数或质量已经很低，接受当前结果
            else {
              console.warn(`达到最大尝试次数或质量下限(${quality.toFixed(2)})，停止压缩`);
            }
            
            // 创建新的File对象
            const compressedFile = new File([blob], file.name || `compressed-image-${Date.now()}.jpg`, {
              type: 'image/jpeg',
              lastModified: Date.now()
            });
            
            // 如果压缩后比压缩前还大，则返回原文件
            if (compressedFile.size >= file.size) {
              console.warn(`压缩后文件大小(${(compressedFile.size / 1024 / 1024).toFixed(2)}MB)大于原始文件(${fileSizeMB.toFixed(2)}MB)，返回原始文件`);
              resolve(file);
              return;
            }
            
            // 打印压缩信息
            console.log(`图片压缩完成: ${fileSizeMB.toFixed(2)}MB -> ${blobSizeMB.toFixed(2)}MB, 压缩率: ${Math.round((1 - blob.size / file.size) * 100)}%`);
            
            resolve(compressedFile);
          } else {
            // 计算下一次的压缩质量 - 使用更温和的降低策略
            // 仅当尺寸远大于目标时才显著降低质量
            let qualityReduction;
            const sizeRatio = blobSizeMB / targetSize;
            
            if (sizeRatio > 4) {
              qualityReduction = 0.15; // 尺寸过大，降低15%质量
            } else if (sizeRatio > 2) {
              qualityReduction = 0.1; // 尺寸偏大，降低10%质量
            } else {
              qualityReduction = 0.05; // 接近目标，仅降低5%质量
            }
            
            const newQuality = Math.max(0.75, quality * (1 - qualityReduction));
            
            console.log(`大小仍超过目标(比例: ${sizeRatio.toFixed(1)}x)，降低质量至: ${newQuality.toFixed(2)}`);
            compressWithQuality(newQuality, tries + 1);
          }
        }, 'image/jpeg', quality);
      };
      
      // 开始压缩过程
      compressWithQuality(initialQuality);
    };
    
    img.onerror = (error) => {
      clearTimeout(imageLoadTimeout);
      console.error('图片加载失败:', error);
      reject(new Error('图片加载失败'));
    };
  });
};

export default {
  compressImage
}; 